/**
 * Copyright (c) 2018-2023, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 *
 * Contains: 
 *
 * Change Logs:
 * Date           Author            Notes
 * 2023-08-08     Shiroko           Init
 */
#ifndef __DRIVERS_VIRTIO_DEVICES_VIRTIO_NET_H__
#define __DRIVERS_VIRTIO_DEVICES_VIRTIO_NET_H__

#include <nx_configure.h>

#define VIRTIO_NET_QUEUE_RECEIVE_N(N)       (2*(N))     // N starts from 0
#define VIRTIO_NET_QUEUE_TRANSMIT_N(N)      (2*(N)+1)
#define VIRTIO_NET_QUEUE_CONTROL_N(N)       (2*((N)+1))

#define VIRTIO_NET_QUEUE_RECEIVE            VIRTIO_NET_QUEUE_RECEIVE_N(0)
#define VIRTIO_NET_QUEUE_TRANSMIT           VIRTIO_NET_QUEUE_TRANSMIT_N(0)
#define VIRTIO_NET_QUEUE_CONTROL            VIRTIO_NET_QUEUE_CONTROL_N(0)

// Device handles packets with partial checksum. This “checksum offload” is a common features on modern network cards.
#define VIRTIO_NET_FEATURE_CSUM                     (1 << 0)
// Driver handles packets with partial checksum.
#define VIRTIO_NET_FEATURE_GUEST_CSUM               (1 << 1)
// Control channel offloads reconfiguration support.
#define VIRTIO_NET_FEATURE_CTRL_GUEST_OFFLOADS      (1 << 2)
// Device maximum MTU reporting is supported. If offered by the device, device advises driver about the value of its maximum MTU. If negotiated, the driver uses mtu as the maximum MTU value.
#define VIRTIO_NET_FEATURE_MTU                      (1 << 3)
// Device has given MAC address.
#define VIRTIO_NET_FEATURE_MAC                      (1 << 5)
// Driver can receive TSOv4.
#define VIRTIO_NET_FEATURE_GUEST_TSO4               (1 << 7)
// Driver can receive TSOv6.
#define VIRTIO_NET_FEATURE_GUEST_TSO6               (1 << 8)
// Driver can receive TSO with ECN.
#define VIRTIO_NET_FEATURE_GUEST_ECN                (1 << 9)
// Driver can receive UFO.
#define VIRTIO_NET_FEATURE_GUEST_UFO                (1 << 10)
// Device can receive TSOv4.
#define VIRTIO_NET_FEATURE_HOST_TSO4                (1 << 11)
// Device can receive TSOv6.
#define VIRTIO_NET_FEATURE_HOST_TSO6                (1 << 12)
// Device can receive TSO with ECN.
#define VIRTIO_NET_FEATURE_HOST_ECN                 (1 << 13)
// Device can receive UFO.
#define VIRTIO_NET_FEATURE_HOST_UFO                 (1 << 14)
// Driver can merge receive buffers.
#define VIRTIO_NET_FEATURE_MRG_RXBUF                (1 << 15)
// Configuration status field is available.
#define VIRTIO_NET_FEATURE_STATUS                   (1 << 16)
// Control channel is available.
#define VIRTIO_NET_FEATURE_CTRL_VQ                  (1 << 17)
// Control channel RX mode support.
#define VIRTIO_NET_FEATURE_CTRL_RX                  (1 << 18)
// Control channel VLAN filtering.
#define VIRTIO_NET_FEATURE_CTRL_VLAN                (1 << 19)
// Driver can send gratuitous packets.
#define VIRTIO_NET_FEATURE_GUEST_ANNOUNCE           (1 << 21)
// Device supports multiqueue with automatic receive steering.
#define VIRTIO_NET_FEATURE_MQ                       (1 << 22)
// Set MAC address through control channel.
#define VIRTIO_NET_FEATURE_CTRL_MAC_ADDR            (1 << 23)
// Device can receive USO packets. Unlike UFO (fragmenting the packet) the USO splits large UDP packet to several segments when each of these smaller packets has UDP header.
#define VIRTIO_NET_FEATURE_HOST_USO                 (1 << 56)
// Device can report per-packet hash value and a type of calculated hash.
#define VIRTIO_NET_FEATURE_HASH_REPORT              (1 << 57)
// Driver can provide the exact hdr_len value. Device benefits from knowing the exact header length.
#define VIRTIO_NET_FEATURE_GUEST_HDRLEN             (1 << 59)
// Device supports RSS (receive-side scaling) with Toeplitz hash calculation and configurable hash parameters for receive steering.
#define VIRTIO_NET_FEATURE_RSS                      (1 << 60)
// Device can process duplicated ACKs and report number of coalesced segments and duplicated ACKs.
#define VIRTIO_NET_FEATURE_RSC_EXT                  (1 << 61)
// Device may act as a standby for a primary device with the same MAC address.
#define VIRTIO_NET_FEATURE_STANDBY                  (1 << 62)
// Device reports speed and duplex.
#define VIRTIO_NET_FEATURE_SPEED_DUPLEX             (1 << 63)

#define VIRTIO_NET_MSS  (1500 + 6 + 6 + 2)

struct VirtioNetDeviceConfig
{
    NX_U8 mac[6];
#define VIRTIO_NET_STATUS_LINK_UP                   (1 << 0)
#define VIRTIO_NET_STATUS_ANNOUNCE                  (1 << 1)
    NX_U16 status;
    /*
    NX_U16 max_virtqueue_pairs;
    NX_U16 mtu;
    NX_U32 speed;
    NX_U8 duplex;
    NX_U8 rss_max_key_size;
    NX_U16 rss_max_indirection_table_length;
    NX_U32 supported_hash_types;
     */
};
typedef struct VirtioNetDeviceConfig    VirtioNetDeviceConfig;

struct VirtioNetHeader
{
#define VIRTIO_NET_HDR_F_NEEDS_CSUM    1
#define VIRTIO_NET_HDR_F_DATA_VALID    2
#define VIRTIO_NET_HDR_F_RSC_INFO      4
    NX_U8 flags;
#define VIRTIO_NET_HDR_GSO_NONE        0
#define VIRTIO_NET_HDR_GSO_TCPV4       1
#define VIRTIO_NET_HDR_GSO_UDP         3
#define VIRTIO_NET_HDR_GSO_TCPV6       4
#define VIRTIO_NET_HDR_GSO_UDP_L4      5
#define VIRTIO_NET_HDR_GSO_ECN      0x80
    NX_U8  gso_type;
    NX_U16 hdr_len;
    NX_U16 gso_size;
    NX_U16 csum_start;
    NX_U16 csum_offset;
    NX_U16 num_buffers;
    // NX_U32 hash_value;        // (Only if VIRTIO_NET_F_HASH_REPORT negotiated)
    // NX_U16 hash_report;       // (Only if VIRTIO_NET_F_HASH_REPORT negotiated)
    // NX_U16 padding_reserved;  // (Only if VIRTIO_NET_F_HASH_REPORT negotiated)
}__attribute__((packed));
typedef struct VirtioNetHeader          VirtioNetHeader;

struct VirtioNetDeviceExtension
{
    NX_U8                    mac[6];
    NX_U16                   status;
    struct
    {
        VirtioNetHeader header;
        NX_U8           buffer[VIRTIO_NET_MSS];
    } transmit_buffer[CONFIG_NX_DRIVER_VIRTIO_SPLIT_QUEUE_SIZE];
    struct
    {
        VirtioNetHeader header;
        NX_U8           buffer[VIRTIO_NET_MSS];
    } receive_buffer[CONFIG_NX_DRIVER_VIRTIO_SPLIT_QUEUE_SIZE];
    NX_Fifo *received_ids;
};
typedef struct VirtioNetDeviceExtension VirtioNetDeviceExtension;

// Public interface
#define VIRTIO_NET_CMD_GET_MAC  0x100
#define VIRTIO_NET_CMD_FLUSH    0x101

#endif // __DRIVERS_VIRTIO_DEVICES_VIRTIO_NET_H__
